﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using System.ServiceModel;
using PumeCentralService;

namespace PumpeStation
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    [CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
    public partial class MainWindow : Window, IPumpCentralCallback
    {
        private double waterLevel;
        private double PumpCapacityPrTimeUnit;
        private string ID;
        private Status status;

        private DispatcherTimer waterLevelIncreseTimer = new DispatcherTimer();
        private DispatcherTimer pumpTimer = new DispatcherTimer();

        IPumpCentralCallback central;
        IPumpCentalService centralServiceConnection = null;

        public MainWindow(string id)
        {
            InitializeComponent();
            ID = id;
            waterLevel = 10;

            SetWaterLevelTimerProperties();
            SetPumpTimerProperties();

            SubscribeToService();

            waterLevelIncreseTimer.Start();
            waterLevelIncreseTimer.Start();
            StartPump();

            Lbl_IDText.Content = this.ID;
            Lbl_RunningStatus_Text.Content = GetStatus();
        }

        private string GetStatus()
        {
            switch (status)
            {
                case Status.active:
                    return "Active";
                case Status.inactive:
                    return "Inactive";
                case Status.faulted:
                    return "Faulted";
                default:
                    return "Error";
            }
        }

        private void SubscribeToService() // LOGIN
        {
            try
            {
                DuplexChannelFactory<IPumpCentalService> pumpCentralChannalFactory = new DuplexChannelFactory<IPumpCentalService>(new InstanceContext(this), new NetTcpBinding(), PumpCentralServiceKonstants.URI);
                centralServiceConnection = pumpCentralChannalFactory.CreateChannel();
                centralServiceConnection.SubscribeFromPump(new PumpStatusDTO() { waterLevel = this.waterLevel, ID = this.ID, status = this.status });
            }
            catch (CommunicationException ce)
            {
                MessageBox.Show("Login Failed");
                Lbl_ConnectionStatus_Text.Content = "Disconnected";
            }
        }

        private void Unsubscribe()
        {
            try
            {
                DuplexChannelFactory<IPumpCentalService> pumpCentralChannalFactory = new DuplexChannelFactory<IPumpCentalService>(new InstanceContext(this), new NetTcpBinding(), PumpCentralServiceKonstants.URI);
                IPumpCentalService centralChannel = pumpCentralChannalFactory.CreateChannel();
                centralChannel.UnSubscribePump(new PumpStatusDTO() { waterLevel = this.waterLevel, ID = this.ID, status = this.status });
            }
            catch (CommunicationException ce)
            {
                MessageBox.Show("Logout Failed");
            }
        }

        private void SetPumpTimerProperties()
        {
            pumpTimer.Interval = new TimeSpan(0, 0, 1);
            pumpTimer.Tick += pumpTimer_Tick;
        }

        private void SetWaterLevelTimerProperties()
        {
            waterLevelIncreseTimer.Interval = new TimeSpan(0, 0, 2);
            waterLevelIncreseTimer.Tick += waterLevelIncreseTimer_Tick;
        }

        void pumpTimer_Tick(object sender, EventArgs e)
        {
            if (status == Status.active)
            {
                if (waterLevel < 3)
                {
                    waterLevel = 0;

                }
                else
                {
                    waterLevel -= 3;
                }

                Lbl_Waterlevel_Text.Content = this.waterLevel;
            }
        }        

        void waterLevelIncreseTimer_Tick(object sender, EventArgs e)
        {
            waterLevel += 5;
            Lbl_Waterlevel_Text.Content = this.waterLevel;
        }

        public bool StartPump()
        {
            MessageBox.Show("Starter Pumpen");
            if (status != Status.faulted)
            {
                status = Status.active;                
                pumpTimer.Start();

                return true;
            }
            return false;            
        }

        public bool StopPump()
        {
            if (status != Status.faulted)
            {
                status = Status.inactive;
                return true;
            }
            return false;
        }

        public void CauseFault()
        {
            status = Status.faulted;
        }

        public void RepairFault()
        {
            status = Status.active;
        }

        public bool RegisterPump(PumpStatusDTO dto)
        {
            PumpStatusDTO PumpDto = new PumpStatusDTO() { ID = this.ID, waterLevel = this.waterLevel, status = this.status };

            try
            {
                DuplexChannelFactory<IPumpCentralCallback> CallbackFactory = new DuplexChannelFactory<IPumpCentralCallback>(new InstanceContext(this), new NetTcpBinding(), new EndpointAddress(PumpCentralServiceKonstants.URI));
                central = CallbackFactory.CreateChannel();
                bool success = central.RegisterPump(PumpDto);

                if (success)
                {
                    return true;
                }

                else
                {
                    MessageBox.Show("Registration Failed");
                    return false;
                }
                
            }
            catch (Exception e)
            {
                return false;
            }

        }

        public bool UnregisterPump(PumpStatusDTO dto)
        {
            PumpStatusDTO PumpDto = new PumpStatusDTO() { ID = this.ID, waterLevel = this.waterLevel, status = this.status };

            try
            {
                DuplexChannelFactory<IPumpCentralCallback> CallbackFactory = new DuplexChannelFactory<IPumpCentralCallback>(new InstanceContext(this), new NetTcpBinding(), new EndpointAddress(PumpCentralServiceKonstants.URI));
                central = CallbackFactory.CreateChannel();
                bool success = central.UnregisterPump(PumpDto);

                if (success)
                {
                    return true;
                }

                else
                {
                    MessageBox.Show("Registration Failed");
                    return false;
                }

            }
            catch (Exception e)
            {
                return false;
            }
        }

        public double getWaterLevel()
        {
            return waterLevel;
        }

        public PumpStatusDTO GetData()
        {
            PumpStatusDTO dto = new PumpStatusDTO(){waterLevel = this.waterLevel, ID = this.ID, status = this.status};

            return dto;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            if (status == Status.active || status == Status.inactive)
            {
                status = Status.faulted;
            }
            else
            {
                status = Status.active;
            }
        }
    }
}
